package com.dashu.core.service;

import com.dashu.base.utils.UIDUtil;
import com.dashu.base.utils.VerificationUtil;
import com.dashu.core.dto.attendance.*;
import com.dashu.core.model.*;
import com.dashu.core.result.PageEnty;
import com.dashu.base.utils.CopyUtil;
import com.dashu.core.vo.attendancek.AttendanceRuleListVO;
import com.dashu.core.vo.attendancek.AttendanceRuleVO;
import com.dashu.core.vo.UpdateEntityVO;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.FlushModeType;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AttendanceRuleService extends DataService {


    @Autowired
    private AttendanceGroupService attendanceGroupService;
    @Autowired
    private AttendanceDateService attendanceDateService;
    @Autowired
    private AttendanceTimeService attendanceTimeService;

    @Transactional
    public AttendanceRuleDTO add(AttendanceRuleVO attendanceRuleVO) {
        AttendancekRule attendancekRule = CopyUtil.copyEnty(attendanceRuleVO, AttendancekRule.class);
        try {
            long userId = Long.parseLong(VerificationUtil.getUserId());
            attendancekRule.setId(UIDUtil.nextId());
            attendancekRule.setCreateUser(userId);
            attendancekRule.setCreateTime(System.currentTimeMillis());
            attendancekRule.setRuleType(attendanceRuleVO.getRuleType());
            attendancekRule.setRuleInType(attendanceRuleVO.getRuleInType());
            attendanceRuleVO.getAttendancekDate().stream().forEach(ad -> {
                ad.setRuleId(attendancekRule.getId());
                attendanceDateService.add(ad);
            });
            attendanceRuleVO.getAttendancekGroup().stream().forEach(ag -> {
                ag.setRuleId(attendancekRule.getId());
                ag.setRuleType(attendanceRuleVO.getRuleType());
                ag.setRuleInType(attendanceRuleVO.getRuleInType());
                ag.setAtBaseId(attendanceRuleVO.getAtBaseId());
                attendanceGroupService.add(ag);
            });
            entityManager.persist(attendancekRule);
//            entityManager.flush();
            entityManager.setFlushMode(FlushModeType.AUTO);


        } catch (Exception e) {
            e.printStackTrace();
        }
        AttendanceRuleDTO attendanceRuleDTO = CopyUtil.copyEnty(attendancekRule, AttendanceRuleDTO.class);
        return attendanceRuleDTO;

    }

    @Transactional
    public boolean deleteByAttendancekRuleId(long attendancekRuleId) throws Exception {
        QAttendancekRule qAttendancekRule = QAttendancekRule.attendancekRule;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qAttendancekRule.id.eq(attendancekRuleId));
        AttendancekRule attendancekRule =
                queryFactory
                        .select(qAttendancekRule)
                        .from(qAttendancekRule)
                        .where(booleanBuilder.getValue())
                        .fetchOne();
        attendanceDateService.deleteAttendanceData(attendancekRuleId);
        attendanceGroupService.deleteAttendanceGroup(attendancekRuleId, attendancekRule.getRuleType(), attendancekRule.getRuleInType());
        entityManager.remove(attendancekRule);
//            entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        return true;

    }

    @Transactional
    public AttendanceRuleDTO updataByAttendancekRuleId(UpdateEntityVO<AttendanceRuleVO> updateAttendancekRuleVO) throws Exception {
        QAttendancekRule qAttendancekRule = QAttendancekRule.attendancekRule;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        AttendanceRuleVO attendanceRuleVO = updateAttendancekRuleVO.getEntityVO();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qAttendancekRule.id.eq(updateAttendancekRuleVO.getId()));
        AttendancekRule attendancekRule;
        try {
            attendancekRule =
                    queryFactory
                            .select(qAttendancekRule)
                            .from(qAttendancekRule)
                            .where(booleanBuilder.getValue())
                            .fetchOne();
            attendanceDateService.updataAttendanceData(attendanceRuleVO.getAttendancekDate(), attendancekRule.getId());
            attendanceGroupService.updataAttendanceGroup(attendanceRuleVO.getAttendancekGroup(), attendancekRule.getId(), attendancekRule.getRuleType(), attendancekRule.getRuleInType());
            attendancekRule.setUpdateUser(userId);
            attendancekRule.setUpdateTime(new Date().getTime());
            attendancekRule = entityManager.merge(attendancekRule);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
//        entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        AttendanceRuleDTO AttendanceRuleDTO = CopyUtil.copyEnty(attendancekRule, AttendanceRuleDTO.class);
        return AttendanceRuleDTO;

    }

    public List<AttendanceRuleDTO> findByCreteUser(PageEnty<Long> baseVo) {
        QAttendancekRule qAttendancekRule = QAttendancekRule.attendancekRule;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qAttendancekRule.createUser.eq(baseVo.getBaseId()));
        List<AttendancekRule> attendancekRules = queryFactory
                .select(qAttendancekRule)
                .from(qAttendancekRule)
                .where(booleanBuilder.getValue())
                .fetch();
        List<AttendanceRuleDTO> recycleDTOS = CopyUtil.copyList(attendancekRules, AttendanceRuleDTO.class);
        return recycleDTOS;

    }

    public AttendanceRuleDTO existByName( long atBaseId , String name) {
        QAttendancekRule qAttendancekRule = QAttendancekRule.attendancekRule;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qAttendancekRule.atBaseId.eq(atBaseId));
        booleanBuilder.and(qAttendancekRule.ruleName.eq(name));
        AttendancekRule attendancekRule = queryFactory
                .select(qAttendancekRule)
                .from(qAttendancekRule)
                .where(booleanBuilder.getValue())
                .fetchOne();
        AttendanceRuleDTO recycleDTO = CopyUtil.copyEnty(attendancekRule, AttendanceRuleDTO.class);
        return recycleDTO;

    }

    public AttendanceRuleDTO findByAttendancekRuleId(long attendancekRuleId) {
        QAttendancekRule qAttendancekRule = QAttendancekRule.attendancekRule;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qAttendancekRule.id.eq(attendancekRuleId));
        AttendancekRule attendancekRule =
                queryFactory
                        .select(qAttendancekRule)
                        .from(qAttendancekRule)
                        .where(booleanBuilder.getValue())
                        .fetchOne();
        List<AttendanceDateDTO> attendanceDateDTOList = attendanceDateService.findAttendanceGroup(attendancekRuleId);
        attendanceDateDTOList.stream().forEach(add -> {
            AttendanceTimeDTO attendanceTimeDTO = attendanceTimeService.findAttendancekGroup(add.getTimeId());
            add.setTimeId(add.getTimeId());
            add.setRuleId(attendanceTimeDTO.getRuleId());
            add.setStartDate1(attendanceTimeDTO.getStartDate1());
            add.setStartDate2(attendanceTimeDTO.getStartDate2());
            add.setStartDate3(attendanceTimeDTO.getStartDate3());
            add.setEndDate1(attendanceTimeDTO.getEndDate1());
            add.setEndDate2(attendanceTimeDTO.getEndDate2());
            add.setEndDate3(attendanceTimeDTO.getEndDate3());
            add.setName(attendanceTimeDTO.getName());
            add.setOpen(attendanceTimeDTO.getOpen());
        });
        List<AttendanceGroupDTO> attendanceGroupDTOList = attendanceGroupService.findAttendanceGroup(attendancekRuleId);
        AttendanceRuleDTO attendanceRuleDTO = CopyUtil.copyEnty(attendancekRule, AttendanceRuleDTO.class);
        attendanceRuleDTO.setAttendancekDate(attendanceDateDTOList);
        attendanceRuleDTO.setAttendancekGroup(attendanceGroupDTOList);
        return attendanceRuleDTO;

    }

    public long ruleListCount(PageEnty<AttendanceRuleListVO> rulePageEntyListVO) {

        long baseId = rulePageEntyListVO.getBaseId() == 0 ? Long.parseLong(VerificationUtil.getUserId()) : rulePageEntyListVO.getBaseId();
        AttendanceRuleListVO attendanceRuleListVO = rulePageEntyListVO.getVo();
        QAttendancekRule qAttendancekRule = QAttendancekRule.attendancekRule;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qAttendancekRule.createUser.eq(baseId));
        if (!StringUtils.isEmpty(attendanceRuleListVO.getRuleName()))
            booleanBuilder.and(qAttendancekRule.createUser.eq(baseId));
        long count = queryFactory
                .select(qAttendancekRule)
                .from(qAttendancekRule)
                .where(booleanBuilder.getValue())
                .fetchCount();
        return count;

    }

    public List<AttendanceRuleListDTO> pageAttendancekRuleList(PageEnty<AttendanceRuleListVO> rulePageEntyListVO) {
        List<AttendanceRuleListDTO> attendanceRuleListDTOS = Lists.newArrayList();
        long baseId = rulePageEntyListVO.getBaseId() == 0 ? Long.parseLong(VerificationUtil.getUserId()) : rulePageEntyListVO.getBaseId();
        AttendanceRuleListVO attendanceRuleListVO = rulePageEntyListVO.getVo();
        QAttendancekRule qAttendancekRule = QAttendancekRule.attendancekRule;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qAttendancekRule.createUser.eq(baseId));
        if (!StringUtils.isEmpty(attendanceRuleListVO.getRuleName()))
            booleanBuilder.and(qAttendancekRule.ruleName.like("%" + attendanceRuleListVO.getRuleName() + "%"));
        List<AttendancekRule> attendancekRules = queryFactory
                .select(qAttendancekRule)
                .from(qAttendancekRule)
                .where(booleanBuilder.getValue())
                .fetch();
        attendancekRules.stream().forEach(ar -> {
            AttendanceRuleListDTO attendanceRuleListDTO = CopyUtil.copyEnty(ar, AttendanceRuleListDTO.class);
            List<AttendanceDateDTO> attendanceDateDTOS = attendanceDateService.findAttendanceGroup(ar.getId());
            attendanceDateDTOS.stream().forEach(add -> {
                AttendanceTimeDTO attendanceTimeDTO = attendanceTimeService.                                                    findAttendancekGroup(add.getTimeId());
                add.setTimeId(add.getTimeId());
                add.setRuleId(attendanceTimeDTO.getRuleId());
                add.setStartDate1(attendanceTimeDTO.getStartDate1());
                add.setStartDate2(attendanceTimeDTO.getStartDate2());
                add.setStartDate3(attendanceTimeDTO.getStartDate3());
                add.setEndDate1(attendanceTimeDTO.getEndDate1());
                add.setEndDate2(attendanceTimeDTO.getEndDate2());
                add.setEndDate3(attendanceTimeDTO.getEndDate3());
                add.setName(attendanceTimeDTO.getName());
                add.setOpen(attendanceTimeDTO.getOpen());
            });
            attendanceRuleListDTO.setAttendancekDate(attendanceDateDTOS);
            attendanceRuleListDTO.setRuleName(ar.getRuleName());
            attendanceRuleListDTO.setRuleType(ar.getRuleType());
            attendanceRuleListDTO.setRuleInType(ar.getRuleInType());
            attendanceRuleListDTO.setCompanyId(ar.getAtBaseId());
            if (!ar.getRuleType().equals("TEACHER")) {
                List<AttendanceGroupDTO> attendanceGroupeDTOS = attendanceGroupService.findAttendanceGroup(ar.getId());
                attendanceRuleListDTO.setAttendanceGroup(attendanceGroupeDTOS);
            } else {
                List<AttendanceGroupDTO> attendanceGroupeDTOS = attendanceGroupService.findAttendanceGroup(ar.getId());
                List<AttendanceGroupDTO> teacharTypes = attendanceGroupeDTOS.stream().filter(ag -> !ag.getGroupType().equals("PERSONAL")).collect(Collectors.toList());
                List<AttendanceGroupDTO> teachars = attendanceGroupeDTOS.stream().filter(ag -> ag.getGroupType().equals("PERSONAL")).collect(Collectors.toList());
                attendanceRuleListDTO.setTeacherTypes(teacharTypes);
                attendanceRuleListDTO.setTeachers(teachars);
            }
            attendanceRuleListDTOS.add(attendanceRuleListDTO);
        });

        return attendanceRuleListDTOS;

    }


}
